/**********************************************
 * 
 * File Name				:	CommonDaoImpl.java
 * 
 * Last Changed Date		: 	$Date: 2009-08-01 11:12:53 +0800 (星期六, 01 八月 2009) $
 * 
 * Last Changed Revision	:	$Revision: 86 $
 * 
 * Last Changed Author		:	$Author: cfanboy $
 * 
 * File Header URL			:	$HeadURL: svn://www.svnhost.cn/Busi-Building/code/branch/src/com/busibuilding/common/dao/CommonDaoImpl.java $
 * 
 * ********************************************
 */

package com.busibuilding.common.dao;

import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.transaction.annotation.Transactional;

import com.busibuilding.common.ICommand;
import com.busibuilding.common.exceptions.DAOException;
import com.busibuilding.common.exceptions.OptimisticLockException;
import com.busibuilding.common.pagination.LimitSqlExecutor;
import com.busibuilding.utils.ReflectUtil;

import com.ibatis.common.util.PaginatedList;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;

/**
 * Class Name: CommonDaoImpl.java 
 * Description: This abstract class support the
 * common method for execute database operation
 * 
 * @author: YU Zhipeng
 * @version: 1.0
 * @since: 1.0 Date: 2009-07-10
 */

@SuppressWarnings({ "unchecked", "deprecation" })
@Transactional(rollbackForClassName = { "*Exception" })
public abstract class CommonDaoImpl extends SqlMapClientDaoSupport implements
		ICommonDao, ICommand {
	private static Logger logger = LogManager.getLogger(CommonDaoImpl.class);
	
	private SqlExecutor sqlExecutor; 
	public SqlExecutor getSqlExecutor() {  
        return sqlExecutor;  
    }  

    public void setSqlExecutor(SqlExecutor sqlExecutor) {  
        this.sqlExecutor = sqlExecutor;  
    }   
    
    public void setEnableLimit(boolean enableLimit) {  
        if (sqlExecutor instanceof LimitSqlExecutor) {  
            ((LimitSqlExecutor) sqlExecutor).setEnableLimit(enableLimit);  
        }  
    }   
    
    /**
     * Initialize sqlMapClient
     * @throws Exception
     */
	public void initialize() throws Exception {  
        if (sqlExecutor != null) {  
            SqlMapClient sqlMapClient = getSqlMapClientTemplate()  
                    .getSqlMapClient();  
            if (sqlMapClient instanceof ExtendedSqlMapClient) {  
                ReflectUtil.setFieldValue(((ExtendedSqlMapClient) sqlMapClient)  
                        .getDelegate(), "sqlExecutor", SqlExecutor.class, sqlExecutor);  
            }  
        }  
    }   
	/**
	 * Delete records
	 * 
	 * @param sql
	 * @param obj
	 */
	@Override
	public int delete(String sql, Object obj) throws DAOException {
		int result = SQLMAP_COMMON_RESULT_ERROR;
		try {
			result = getSqlMapClient().delete(sql, obj);
		} catch (SQLException e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_DELETE + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_DELETE, e);
		} catch (Exception e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_DELETE + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_DELETE, e);
		}
		return result;
	}

	/**
	 * Query the object
	 * 
	 * @param sql
	 * @param param
	 * @return Object
	 */
	@Override
	public Object queryObject(String sql, Object param) throws DAOException {
		try {
			return getSqlMapClient().queryForObject(sql, param);
		} catch (SQLException e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		} catch (Exception e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		}

	}

	/**
	 * Insert records
	 * 
	 * @param sql
	 * @param obj
	 */
	@Override
	public Object insert(String sql, Object obj) throws DAOException {
		try {
			return getSqlMapClient().insert(sql, obj);
		} catch (SQLException e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_INSERT + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_INSERT, e);
		} catch (Exception e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_INSERT + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_INSERT, e);
		}

	}

	/**
	 * Query the list
	 * 
	 * @param sql
	 * @param param
	 * @return List
	 */
	@Override
	public List queryList(String sql, Object param) throws DAOException {
		try {
			return getSqlMapClient().queryForList(sql, param);
		} catch (SQLException e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		} catch (Exception e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		}
	}
	
	/**
	 * Query limit recoreds from database  
	 * @param sql
	 * @param param
	 * @param skipResults 
	 * @param maxResults
	 * @return List
	 * @throws DAOException
	 */
	public List queryList(String sql, Object param, int skipResults, int maxResults) throws DAOException{
		try {
			return getSqlMapClient().queryForList(sql, param, skipResults, maxResults);
			
		} catch (SQLException e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		} catch (Exception e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		}
	}
	
	/**
	 * Query limit records from database
	 * @param sql
	 * @param param
	 * @param pageSize
	 * @return PaginatedList
	 * @throws DAOException
	 */
	@Deprecated
	public PaginatedList queryList(String sql, Object param, int pageSize) throws DAOException{
		
		try {
			return getSqlMapClient().queryForPaginatedList(sql, param, pageSize);
			
		} catch (SQLException e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		} catch (Exception e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_QUERY + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_QUERY, e);
		}
	}
	

	/**
	 * Update records
	 * 
	 * @param sql
	 * @param obj
	 */
	@Override
	public int update(String sql, Object obj) throws DAOException {
		int result = SQLMAP_COMMON_RESULT_ERROR;
		try {
			result = getSqlMapClient().update(sql, obj);
			if (result == 0) {
				logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_OPTIMISTIC_LOCK + "\n"
						+ "Execute Sql Statement: " + sql + "\n" + "Object: " + obj.getClass().getName());
				throw new OptimisticLockException(COMMON_DAO_ERROR_OPTIMISTIC_LOCK);
			}
		} catch (SQLException e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_UPDATE + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_UPDATE, e);
		} catch (Exception e) {
			logger.fatal("ErrorCode: " + COMMON_DAO_ERROR_CODE_UPDATE + "\n"
					+ e.getMessage(), e);
			throw new DAOException(COMMON_DAO_ERROR_CODE_UPDATE, e);
		}
		return result;
	}

}
